using System;
using System.Collections;
using System.Diagnostics;
using System.Text;
using ActiproSoftware.SyntaxEditor.Addons.Simple.Ast;

namespace ActiproSoftware.SyntaxEditor.Addons.Simple.Ast {

	/// <summary>
	/// Provides the base class for an AST node visitor.
	/// </summary>
	/// <remarks>
	/// <para>
	/// This class supports the visitor pattern.
	/// </para>
	/// <para>
	/// Each visitor implements a <c>OnVisiting</c> and an <c>OnVisited</c> method for each AST node type.
	/// By default the <c>OnVisiting</c> method returns <c>true</c>, while the <c>OnVisited</c> method does nothing.
	/// </para>
	/// <para>
	/// The <c>OnVisiting</c> method should return <c>true</c> if its child nodes should be visited.
	/// If <c>true</c> is returned, the child nodes are visiting in order.
	/// After the child nodes are visited, the <c>OnVisited</c> method is called.
	/// If <c>OnVisiting</c> returns <c>false</c>, child node visits are not made and <c>OnVisited</c> is called directly.
	/// </para>
	/// <para>
	/// Additionally, the generic <see cref="AstVisitor.OnPreVisiting"/> method is called before any type-specific <c>OnVisiting</c> method is executed
	/// and the generic <see cref="AstVisitor.OnPostVisited"/> method is called after any type-specific <c>OnVisited</c> method is executed.
	/// </para>
	/// </remarks>
	public abstract class AstVisitor {

		/////////////////////////////////////////////////////////////////////////////////////////////////////
		// GENERIC VISIT PROCEDURES
		/////////////////////////////////////////////////////////////////////////////////////////////////////

		/// <summary>
		/// Visits the <see cref="IAstNode"/> after the type-specific <c>OnVisited</c> method is executed.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		public virtual void OnPostVisited(AstNode node) {}

		/// <summary>
		/// Visits the <see cref="IAstNode"/> before the type-specific <c>OnVisiting</c> method is executed.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		/// <returns>
		/// <c>true</c> if the node and its children should be visited; otherwise, <c>false</c>.
		/// </returns>
		public virtual bool OnPreVisiting(AstNode node) {
			return true;
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////
		// VISITING PROCEDURES
		/////////////////////////////////////////////////////////////////////////////////////////////////////

		/// <summary>
		/// Visits the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		/// <returns>
		/// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
		/// </returns>
		public virtual bool OnVisiting(AssignmentStatement node) {
			return true;
		}

		/// <summary>
		/// Visits the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		/// <returns>
		/// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
		/// </returns>
		public virtual bool OnVisiting(BinaryExpression node) {
			return true;
		}

		/// <summary>
		/// Visits the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		/// <returns>
		/// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
		/// </returns>
		public virtual bool OnVisiting(BlockStatement node) {
			return true;
		}

		/// <summary>
		/// Visits the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		/// <returns>
		/// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
		/// </returns>
		public virtual bool OnVisiting(CompilationUnit node) {
			return true;
		}

		/// <summary>
		/// Visits the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		/// <returns>
		/// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
		/// </returns>
		public virtual bool OnVisiting(EmptyStatement node) {
			return true;
		}

		/// <summary>
		/// Visits the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		/// <returns>
		/// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
		/// </returns>
		public virtual bool OnVisiting(FunctionAccessExpression node) {
			return true;
		}

		/// <summary>
		/// Visits the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		/// <returns>
		/// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
		/// </returns>
		public virtual bool OnVisiting(FunctionDeclaration node) {
			return true;
		}

		/// <summary>
		/// Visits the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		/// <returns>
		/// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
		/// </returns>
		public virtual bool OnVisiting(Identifier node) {
			return true;
		}

		/// <summary>
		/// Visits the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		/// <returns>
		/// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
		/// </returns>
		public virtual bool OnVisiting(NumberExpression node) {
			return true;
		}

		/// <summary>
		/// Visits the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		/// <returns>
		/// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
		/// </returns>
		public virtual bool OnVisiting(ParenthesizedExpression node) {
			return true;
		}

		/// <summary>
		/// Visits the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		/// <returns>
		/// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
		/// </returns>
		public virtual bool OnVisiting(ReturnStatement node) {
			return true;
		}

		/// <summary>
		/// Visits the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		/// <returns>
		/// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
		/// </returns>
		public virtual bool OnVisiting(SimpleName node) {
			return true;
		}

		/// <summary>
		/// Visits the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		/// <returns>
		/// <c>true</c> if the node's children should be visited; otherwise, <c>false</c>.
		/// </returns>
		public virtual bool OnVisiting(VariableDeclarationStatement node) {
			return true;
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////
		// VISITED PROCEDURES
		/////////////////////////////////////////////////////////////////////////////////////////////////////

		/// <summary>
		/// Ends the visit of the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		public virtual void OnVisited(AssignmentStatement node) {}

		/// <summary>
		/// Ends the visit of the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		public virtual void OnVisited(BinaryExpression node) {}

		/// <summary>
		/// Ends the visit of the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		public virtual void OnVisited(BlockStatement node) {}

		/// <summary>
		/// Ends the visit of the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		public virtual void OnVisited(CompilationUnit node) {}

		/// <summary>
		/// Ends the visit of the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		public virtual void OnVisited(EmptyStatement node) {}

		/// <summary>
		/// Ends the visit of the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		public virtual void OnVisited(FunctionAccessExpression node) {}

		/// <summary>
		/// Ends the visit of the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		public virtual void OnVisited(FunctionDeclaration node) {}

		/// <summary>
		/// Ends the visit of the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		public virtual void OnVisited(Identifier node) {}

		/// <summary>
		/// Ends the visit of the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		public virtual void OnVisited(NumberExpression node) {}

		/// <summary>
		/// Ends the visit of the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		public virtual void OnVisited(ParenthesizedExpression node) {}

		/// <summary>
		/// Ends the visit of the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		public virtual void OnVisited(ReturnStatement node) {}

		/// <summary>
		/// Ends the visit of the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		public virtual void OnVisited(SimpleName node) {}

		/// <summary>
		/// Ends the visit of the specified type of <see cref="IAstNode"/>.
		/// </summary>
		/// <param name="node">The node to visit.</param>
		public virtual void OnVisited(VariableDeclarationStatement node) {}

	}

}
